package com.qf.security.config;

import com.qf.api.sys.entity.SysUserEntity;
import com.qf.api.sys.service.SysMenuService;
import com.qf.core.constant.URLConstant;
import com.qf.core.exception.BaseException;
import com.qf.core.response.ResponseCode;
import com.qf.core.utils.BeanUtils;
import com.qf.core.utils.ToolUtils;
import com.qf.security.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.function.Supplier;

/**
 * @Author: sin
 * @Date: 2025/5/5 21:08
 * @Description: 动态权限配置
 **/
@Slf4j
@Component
public class MyauthorizationManager  implements AuthorizationManager<RequestAuthorizationContext> {


    @Override
    public void verify(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
        AuthorizationManager.super.verify(authentication, object);
    }

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {
        SysUserEntity userInfo = SecurityUtils.getUserInfo().getUser();
        //获取Spring Boot应用的上下文路径
        String contextPath = requestAuthorizationContext.getRequest().getContextPath();
        //访问的接口地址
        String requestURI = requestAuthorizationContext.getRequest().getRequestURI();
        // 示例返回：GET、POST、PUT、DELETE
        String method = requestAuthorizationContext.getRequest().getMethod();
        // 注意：这里使用startsWith进行检查，以确保只移除实际匹配的上下文路径
        if (requestURI.startsWith(contextPath)) {
            requestURI = requestURI.substring(contextPath.length());
        }
        // 原始路径
        String path = requestURI.substring(URLConstant.ADMIN_URL.length());
        log.info("substring,{}",path);
        log.info("method,{}",method);

        if(Objects.equals(method, "GET")) {
            return new AuthorizationDecision(true);
        }
        // 正则替换将数字ID替换为{id}   /users/8  输出: /users/{id}
        String templatePath = path.replaceAll("/\\d+", "/{id}");
        String perm = loadPermsFromDatabase(templatePath, method);
        if(perm == null || !ToolUtils.containsString(userInfo.getPerms(),perm)) {
            throw new AccessDeniedException(userInfo.getUsername() + ResponseCode.NO_ACCESS.getDesc());
        }
        return new AuthorizationDecision(true);
    }
    private String loadPermsFromDatabase(String path, String method) {
        try {
            // 根据path和菜单类型从数据库获取菜单信息
            return BeanUtils.getBean(SysMenuService.class).selectPermByPathAndType(path,method);
        } catch (Exception e) {
            // 异常处理逻辑
            throw new BaseException(ResponseCode.GET_DATA_ERROR);
        }
    }
}